home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume15 / stevie / part03 < prev    next >
Encoding:
Internet Message Format  |  1988-06-05  |  44.7 KB

  1. Subject:  v15i039:  Stevie, an "aspiring" VI clone for Unix, OS/2, Amiga, Part03/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: onecom!wldrdg!tony (Tony Andrews)
  7. Posting-number: Volume 15, Issue 39
  8. Archive-name: stevie/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 4)."
  17. # Contents:  screen.c search.c stevie.doc
  18. # Wrapped by rsalz@fig.bbn.com on Sun Jun  5 11:45:46 1988
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'screen.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'screen.c'\"
  22. else
  23. echo shar: Extracting \"'screen.c'\" \(13160 characters\)
  24. sed "s/^X//" >'screen.c' <<'END_OF_FILE'
  25. X/*
  26. X * Routines to manipulate the screen representations.
  27. X *
  28. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  29. X *
  30. X */
  31. X
  32. X#include "stevie.h"
  33. X
  34. X/*
  35. X * The following variable is set (in filetonext) to the number of physical
  36. X * lines taken by the line the cursor is on. We use this to avoid extra
  37. X * calls to plines(). The optimized routines lfiletonext() and lnexttoscreen()
  38. X * make sure that the size of the cursor line hasn't changed. If so, lines
  39. X * below the cursor will move up or down and we need to call the routines
  40. X * filetonext() and nexttoscreen() to examine the entire screen.
  41. X */
  42. static    int    Cline_size;    /* size (in rows) of the cursor line */
  43. static    int    Cline_row;    /* starting row of the cursor line */
  44. X
  45. X/*
  46. X * filetonext()
  47. X *
  48. X * Based on the current value of Topchar, transfer a screenfull of
  49. X * stuff from Filemem to Nextscreen, and update Botchar.
  50. X */
  51. X
  52. static void
  53. filetonext()
  54. X{
  55. X    register int row, col;
  56. X    register char *screenp = Nextscreen;
  57. X    LPTR memp;
  58. X    LPTR save;            /* save pos. in case line won't fit */
  59. X    register char *endscreen;
  60. X    register char *nextrow;
  61. X    char extra[16];
  62. X    int nextra = 0;
  63. X    register int c;
  64. X    int n;
  65. X    int done;
  66. X    int srow;        /* starting row of the current line */
  67. X
  68. X    save = memp = *Topchar;
  69. X
  70. X    /* The number of rows shown is Rows-1. */
  71. X    /* The last line is the status/command line. */
  72. X    endscreen = &screenp[(Rows-1)*Columns];
  73. X
  74. X    srow = done = row = col = 0;
  75. X    while ( screenp < endscreen && !done) {
  76. X
  77. X        /* Get the next character to put on the screen. */
  78. X
  79. X        /* The 'extra' array contains the extra stuff that is */
  80. X        /* inserted to represent special characters (tabs, and */
  81. X        /* other non-printable stuff.  The order in the 'extra' */
  82. X        /* array is reversed. */
  83. X
  84. X        if ( nextra > 0 )
  85. X            c = extra[--nextra];
  86. X        else {
  87. X            c = (unsigned)(0xff & gchar(&memp));
  88. X            if (inc(&memp) == -1)
  89. X                done = 1;
  90. X            /* when getting a character from the file, we */
  91. X            /* may have to turn it into something else on */
  92. X            /* the way to putting it into 'Nextscreen'. */
  93. X            if ( c == TAB && !P(P_LS) ) {
  94. X                strcpy(extra,"        ");
  95. X                /* tab amount depends on current column */
  96. X                nextra = ((P(P_TS)-1) - col%P(P_TS));
  97. X                c = ' ';
  98. X            }
  99. X            else if ( c == NUL && P(P_LS) ) {
  100. X                extra[0] = NUL;
  101. X                nextra = 1;
  102. X                c = '$';
  103. X            } else if ( (n = chars[c].ch_size) > 1 ) {
  104. X                char *p;
  105. X                nextra = 0;
  106. X                p = chars[c].ch_str;
  107. X                /* copy 'ch-str'ing into 'extra' in reverse */
  108. X                while ( n > 1 )
  109. X                    extra[nextra++] = p[--n];
  110. X                c = p[0];
  111. X            }
  112. X        }
  113. X
  114. X        if ( c == NUL ) {
  115. X            srow = ++row;
  116. X            /*
  117. X             * Save this position in case the next line won't
  118. X             * fit on the screen completely.
  119. X             */
  120. X            save = memp;
  121. X            /* get pointer to start of next row */
  122. X            nextrow = &Nextscreen[row*Columns];
  123. X            /* blank out the rest of this row */
  124. X            while ( screenp != nextrow )
  125. X                *screenp++ = ' ';
  126. X            col = 0;
  127. X            continue;
  128. X        }
  129. X        if ( col >= Columns ) {
  130. X            row++;
  131. X            col = 0;
  132. X        }
  133. X        /* store the character in Nextscreen */
  134. X        *screenp++ = c;
  135. X        col++;
  136. X    }
  137. X    /*
  138. X     * If we didn't hit the end of the file, and we didn't finish
  139. X     * the last line we were working on, then the line didn't fit.
  140. X     */
  141. X    if (!done && c != NUL) {
  142. X        /*
  143. X         * Clear the rest of the screen and mark the unused lines.
  144. X         */
  145. X        screenp = &Nextscreen[srow * Columns];
  146. X        while (screenp < endscreen)
  147. X            *screenp++ = ' ';
  148. X        for (; srow < (Rows-1) ;srow++)
  149. X            Nextscreen[srow * Columns] = '@';
  150. X        *Botchar = save;
  151. X        return;
  152. X    }
  153. X    /* make sure the rest of the screen is blank */
  154. X    while ( screenp < endscreen )
  155. X        *screenp++ = ' ';
  156. X    /* put '~'s on rows that aren't part of the file. */
  157. X    if ( col != 0 )
  158. X        row++;
  159. X    while ( row < Rows ) {
  160. X        Nextscreen[row*Columns] = '~';
  161. X        row++;
  162. X    }
  163. X    if (done)    /* we hit the end of the file */
  164. X        *Botchar = *Fileend;
  165. X    else
  166. X        *Botchar = memp;
  167. X}
  168. X
  169. X/*
  170. X * nexttoscreen
  171. X *
  172. X * Transfer the contents of Nextscreen to the screen, using Realscreen
  173. X * to avoid unnecessary output.
  174. X */
  175. static void
  176. nexttoscreen()
  177. X{
  178. X    register char *np = Nextscreen;
  179. X    register char *rp = Realscreen;
  180. X    register char *endscreen;
  181. X    register int row = 0, col = 0;
  182. X    int gorow = -1, gocol = -1;
  183. X
  184. X    endscreen = &np[(Rows-1)*Columns];
  185. X
  186. X    outstr(T_CI);        /* disable cursor */
  187. X
  188. X    for ( ; np < endscreen ; np++,rp++ ) {
  189. X        /* If desired screen (contents of Nextscreen) does not */
  190. X        /* match what's really there, put it there. */
  191. X        if ( *np != *rp ) {
  192. X            /* if we are positioned at the right place, */
  193. X            /* we don't have to use windgoto(). */
  194. X            if (gocol != col || gorow != row) {
  195. X                /*
  196. X                 * If we're just off by one, don't send
  197. X                 * an entire esc. seq. (this happens a lot!)
  198. X                 */
  199. X                if (gorow == row && gocol+1 == col) {
  200. X                    outchar(*(np-1));
  201. X                    gocol++;
  202. X                } else
  203. X                    windgoto(gorow=row,gocol=col);
  204. X            }
  205. X            outchar(*rp = *np);
  206. X            gocol++;
  207. X        }
  208. X        if ( ++col >= Columns ) {
  209. X            col = 0;
  210. X            row++;
  211. X        }
  212. X    }
  213. X    outstr(T_CV);        /* enable cursor again */
  214. X}
  215. X
  216. X/*
  217. X * lfiletonext() - like filetonext() but only for cursor line
  218. X *
  219. X * Returns true if the size of the cursor line (in rows) hasn't changed.
  220. X * This determines whether or not we need to call filetonext() to examine
  221. X * the entire screen for changes.
  222. X */
  223. static bool_t
  224. lfiletonext()
  225. X{
  226. X    register int row, col;
  227. X    register char *screenp;
  228. X    LPTR memp;
  229. X    register char *nextrow;
  230. X    char extra[16];
  231. X    int nextra = 0;
  232. X    register int c;
  233. X    int n;
  234. X    bool_t eof;
  235. X
  236. X    screenp = Nextscreen + (Cline_row * Columns);
  237. X
  238. X    memp = *Curschar;
  239. X    memp.index = 0;
  240. X
  241. X    eof = FALSE;
  242. X    col = 0;
  243. X    row = Cline_row;
  244. X
  245. X    while (!eof) {
  246. X
  247. X        /* Get the next character to put on the screen. */
  248. X
  249. X        /* The 'extra' array contains the extra stuff that is */
  250. X        /* inserted to represent special characters (tabs, and */
  251. X        /* other non-printable stuff.  The order in the 'extra' */
  252. X        /* array is reversed. */
  253. X
  254. X        if ( nextra > 0 )
  255. X            c = extra[--nextra];
  256. X        else {
  257. X            c = (unsigned)(0xff & gchar(&memp));
  258. X            if (inc(&memp) == -1)
  259. X                eof = TRUE;
  260. X            /* when getting a character from the file, we */
  261. X            /* may have to turn it into something else on */
  262. X            /* the way to putting it into 'Nextscreen'. */
  263. X            if ( c == TAB && !P(P_LS) ) {
  264. X                strcpy(extra,"        ");
  265. X                /* tab amount depends on current column */
  266. X                nextra = ((P(P_TS)-1) - col%P(P_TS));
  267. X                c = ' ';
  268. X            } else if ( c == NUL && P(P_LS) ) {
  269. X                extra[0] = NUL;
  270. X                nextra = 1;
  271. X                c = '$';
  272. X            } else if ( c != NUL && (n=chars[c].ch_size) > 1 ) {
  273. X                char *p;
  274. X                nextra = 0;
  275. X                p = chars[c].ch_str;
  276. X                /* copy 'ch-str'ing into 'extra' in reverse */
  277. X                while ( n > 1 )
  278. X                    extra[nextra++] = p[--n];
  279. X                c = p[0];
  280. X            }
  281. X        }
  282. X
  283. X        if ( c == NUL ) {
  284. X            row++;
  285. X            /* get pointer to start of next row */
  286. X            nextrow = &Nextscreen[row*Columns];
  287. X            /* blank out the rest of this row */
  288. X            while ( screenp != nextrow )
  289. X                *screenp++ = ' ';
  290. X            col = 0;
  291. X            break;
  292. X        }
  293. X
  294. X        if ( col >= Columns ) {
  295. X            row++;
  296. X            col = 0;
  297. X        }
  298. X        /* store the character in Nextscreen */
  299. X        *screenp++ = c;
  300. X        col++;
  301. X    }
  302. X    return ((row - Cline_row) == Cline_size);
  303. X}
  304. X
  305. X/*
  306. X * lnexttoscreen
  307. X *
  308. X * Like nexttoscreen() but only for the cursor line.
  309. X */
  310. static void
  311. lnexttoscreen()
  312. X{
  313. X    register char *np = Nextscreen + (Cline_row * Columns);
  314. X    register char *rp = Realscreen + (Cline_row * Columns);
  315. X    register char *endline;
  316. X    register int row, col;
  317. X    int gorow = -1, gocol = -1;
  318. X
  319. X    endline = np + (Cline_size * Columns);
  320. X
  321. X    row = Cline_row;
  322. X    col = 0;
  323. X
  324. X    outstr(T_CI);        /* disable cursor */
  325. X
  326. X    for ( ; np < endline ; np++,rp++ ) {
  327. X        /* If desired screen (contents of Nextscreen) does not */
  328. X        /* match what's really there, put it there. */
  329. X        if ( *np != *rp ) {
  330. X            /* if we are positioned at the right place, */
  331. X            /* we don't have to use windgoto(). */
  332. X            if (gocol != col || gorow != row) {
  333. X                /*
  334. X                 * If we're just off by one, don't send
  335. X                 * an entire esc. seq. (this happens a lot!)
  336. X                 */
  337. X                if (gorow == row && gocol+1 == col) {
  338. X                    outchar(*(np-1));
  339. X                    gocol++;
  340. X                } else
  341. X                    windgoto(gorow=row,gocol=col);
  342. X            }
  343. X            outchar(*rp = *np);
  344. X            gocol++;
  345. X        }
  346. X        if ( ++col >= Columns ) {
  347. X            col = 0;
  348. X            row++;
  349. X        }
  350. X    }
  351. X    outstr(T_CV);        /* enable cursor again */
  352. X}
  353. X
  354. X/*
  355. X * updateline() - update the line the cursor is on
  356. X *
  357. X * Updateline() is called after changes that only affect the line that
  358. X * the cursor is on. This improves performance tremendously for normal
  359. X * insert mode operation. The only thing we have to watch for is when
  360. X * the cursor line grows or shrinks around a row boundary. This means
  361. X * we have to repaint other parts of the screen appropriately. If
  362. X * lfiletonext() returns FALSE, the size of the cursor line (in rows)
  363. X * has changed and we have to call updatescreen() to do a complete job.
  364. X */
  365. void
  366. updateline()
  367. X{
  368. X    if (!lfiletonext())
  369. X        updatescreen();        /* bag it, do the whole screen */
  370. X    else
  371. X        lnexttoscreen();
  372. X}
  373. X
  374. void
  375. updatescreen()
  376. X{
  377. X    filetonext();
  378. X    nexttoscreen();
  379. X}
  380. X
  381. void
  382. screenclear()
  383. X{
  384. X    register char    *rp, *np;
  385. X    register char    *end;
  386. X
  387. X    outstr(T_ED);        /* clear the display */
  388. X
  389. X    rp  = Realscreen;
  390. X    end = Realscreen + Rows * Columns;
  391. X    np  = Nextscreen;
  392. X
  393. X    /* blank out the stored screens */
  394. X    while (rp != end)
  395. X        *rp++ = *np++ = ' ';
  396. X}
  397. X
  398. void
  399. cursupdate()
  400. X{
  401. X    LPTR *p;
  402. X    int inc, c, nlines;
  403. X    int i;
  404. X    int didinc;
  405. X
  406. X    if (bufempty()) {        /* special case - file is empty */
  407. X        *Topchar  = *Filemem;
  408. X        *Curschar = *Filemem;
  409. X    } else if ( LINEOF(Curschar) < LINEOF(Topchar) ) {
  410. X        nlines = cntllines(Curschar,Topchar);
  411. X        /* if the cursor is above the top of */
  412. X        /* the screen, put it at the top of the screen.. */
  413. X        *Topchar = *Curschar;
  414. X        Topchar->index = 0;
  415. X        /* ... and, if we weren't very close to begin with, */
  416. X        /* we scroll so that the line is close to the middle. */
  417. X        if ( nlines > Rows/3 ) {
  418. X            for (i=0, p = Topchar; i < Rows/3 ;i++, *Topchar = *p)
  419. X                if ((p = prevline(p)) == NULL)
  420. X                    break;
  421. X        } else
  422. X            s_ins(0, nlines-1);
  423. X        updatescreen();
  424. X    }
  425. X    else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  426. X        nlines = cntllines(Botchar,Curschar);
  427. X        /* If the cursor is off the bottom of the screen, */
  428. X        /* put it at the top of the screen.. */
  429. X        /* ... and back up */
  430. X        if ( nlines > Rows/3 ) {
  431. X            p = Curschar;
  432. X            for (i=0; i < (2*Rows)/3 ;i++)
  433. X                if ((p = prevline(p)) == NULL)
  434. X                    break;
  435. X            *Topchar = *p;
  436. X        } else {
  437. X            scrollup(nlines);
  438. X        }
  439. X        updatescreen();
  440. X    }
  441. X
  442. X    Cursrow = Curscol = Cursvcol = 0;
  443. X    for ( p=Topchar; p->linep != Curschar->linep ;p = nextline(p) )
  444. X        Cursrow += plines(p);
  445. X
  446. X    Cline_row = Cursrow;
  447. X    Cline_size = plines(p);
  448. X
  449. X    for (i=0; i <= Curschar->index ;i++) {
  450. X        c = Curschar->linep->s[i];
  451. X        /* A tab gets expanded, depending on the current column */
  452. X        if ( c == TAB && !P(P_LS) )
  453. X            inc = P(P_TS) - (Curscol % P(P_TS));
  454. X        else
  455. X            inc = chars[(unsigned)(c & 0xff)].ch_size;
  456. X        Curscol += inc;
  457. X        Cursvcol += inc;
  458. X        if ( Curscol >= Columns ) {
  459. X            Curscol -= Columns;
  460. X            Cursrow++;
  461. X            didinc = TRUE;
  462. X        }
  463. X        else
  464. X            didinc = FALSE;
  465. X    }
  466. X    if (didinc)
  467. X        Cursrow--;
  468. X
  469. X    if (c == TAB && State == NORMAL && !P(P_LS)) {
  470. X        Curscol--;
  471. X        Cursvcol--;
  472. X    } else {
  473. X        Curscol -= inc;
  474. X        Cursvcol -= inc;
  475. X    }
  476. X    if (Curscol < 0)
  477. X        Curscol += Columns;
  478. X
  479. X    if (set_want_col) {
  480. X        Curswant = Cursvcol;
  481. X        set_want_col = FALSE;
  482. X    }
  483. X}
  484. X
  485. X/*
  486. X * The rest of the routines in this file perform screen manipulations.
  487. X * The given operation is performed physically on the screen. The
  488. X * corresponding change is also made to the internal screen image.
  489. X * In this way, the editor anticipates the effect of editing changes
  490. X * on the appearance of the screen. That way, when we call screenupdate
  491. X * a complete redraw isn't usually necessary. Another advantage is that
  492. X * we can keep adding code to anticipate screen changes, and in the
  493. X * meantime, everything still works.
  494. X */
  495. X
  496. X/*
  497. X * s_ins(row, nlines) - insert 'nlines' lines at 'row'
  498. X */
  499. void
  500. s_ins(row, nlines)
  501. int    row;
  502. int    nlines;
  503. X{
  504. X    register char    *s, *d;        /* src & dest for block copy */
  505. X    register char    *e;        /* end point for copy */
  506. X    register int    i;
  507. X
  508. X    if (T_IL[0] == NUL)        /* can't do it */
  509. X        return;
  510. X
  511. X    /*
  512. X     * It "looks" better if we do all the inserts at once
  513. X     */
  514. X    outstr(T_SC);            /* save position */
  515. X
  516. X    for (i=0; i < nlines ;i++) {
  517. X        windgoto(row, 0);
  518. X        outstr(T_IL);
  519. X    }
  520. X
  521. X    windgoto(Rows-1, 0);    /* delete any garbage that may have */
  522. X    outstr(T_EL);        /* been shifted to the bottom line */
  523. X    outstr(T_RC);        /* restore the cursor position */
  524. X
  525. X    /*
  526. X     * Now do a block move to update the internal screen image
  527. X     */
  528. X    d = Realscreen + (Columns * (Rows - 1)) - 1;
  529. X    s = d - (Columns * nlines);
  530. X    e = Realscreen + (Columns * row);
  531. X
  532. X    while (s >= e)
  533. X        *d-- = *s--;
  534. X
  535. X    /*
  536. X     * Clear the inserted lines
  537. X     */
  538. X    s = Realscreen + (row * Columns);
  539. X    e = s + (nlines * Columns);
  540. X    while (s < e)
  541. X        *s++ = ' ';
  542. X}
  543. X
  544. X/*
  545. X * s_del(row, nlines) - delete 'nlines' lines at 'row'
  546. X */
  547. void
  548. s_del(row, nlines)
  549. int    row;
  550. int    nlines;
  551. X{
  552. X    register char    *s, *d, *e;
  553. X    register int    i;
  554. X
  555. X    if (T_DL[0] == NUL)            /* can't do it */
  556. X        return;
  557. X
  558. X    /* delete the lines */
  559. X    outstr(T_SC);                /* save position */
  560. X    for (i=0; i < nlines ;i++) {
  561. X        windgoto(row, 0);
  562. X        outstr(T_DL);            /* delete a line */
  563. X        if (i == 0) {
  564. X            windgoto(Rows-2, 0);    /* delete any garbage that */
  565. X            outstr(T_EL);        /* was on the status line */
  566. X        }
  567. X    }
  568. X    outstr(T_RC);                /* restore position */
  569. X
  570. X    /*
  571. X     * do a block move to update the internal image
  572. X     */
  573. X    d = Realscreen + (row * Columns);
  574. X    s = d + (nlines * Columns);
  575. X    e = Realscreen + ((Rows - 1) * Columns);
  576. X
  577. X    while (s < e)
  578. X        *d++ = *s++;
  579. X
  580. X    while (d < e)        /* clear the lines at the bottom */
  581. X        *d++ = ' ';
  582. X}
  583. END_OF_FILE
  584. if test 13160 -ne `wc -c <'screen.c'`; then
  585.     echo shar: \"'screen.c'\" unpacked with wrong size!
  586. fi
  587. # end of 'screen.c'
  588. fi
  589. if test -f 'search.c' -a "${1}" != "-c" ; then 
  590.   echo shar: Will not clobber existing file \"'search.c'\"
  591. else
  592. echo shar: Extracting \"'search.c'\" \(13221 characters\)
  593. sed "s/^X//" >'search.c' <<'END_OF_FILE'
  594. X/*
  595. X * STevie - ST editor for VI enthusiasts.    ...Tim Thompson...twitch!tjt...
  596. X *
  597. X * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  598. X *
  599. X */
  600. X
  601. X#include "stevie.h"
  602. X
  603. X#include <regexp.h>    /* Henry Spencer's regular expression routines */
  604. X
  605. X#ifdef    MEGAMAX
  606. overlay "search"
  607. X#endif
  608. X
  609. X/*
  610. X * This file contains various searching-related routines. These fall into
  611. X * three groups: string searches (for /, ?, n, and N), character searches
  612. X * within a single line (for f, F, t, T, etc), and "other" kinds of searches
  613. X * like the '%' command, and 'word' searches.
  614. X */
  615. X
  616. X/*
  617. X * String searches
  618. X *
  619. X * The actual searches are done using Henry Spencer's regular expression
  620. X * library.
  621. X */
  622. X
  623. X#define    BEGWORD    "([^a-zA-Z0-9_]|^)"    /* replaces "\<" in search strings */
  624. X#define    ENDWORD    "([^a-zA-Z0-9_]|$)"    /* likewise replaces "\>" */
  625. X
  626. bool_t    begword;    /* does the search include a 'begin word' match */
  627. X
  628. X/*
  629. X * mapstring(s) - map special backslash sequences
  630. X */
  631. static char *
  632. mapstring(s)
  633. register char    *s;
  634. X{
  635. X    static    char    ns[80];
  636. X    char    *p;
  637. X
  638. X    begword = FALSE;
  639. X
  640. X    for (p = ns; *s ;s++) {
  641. X        if (*s != '\\') {    /* not an escape */
  642. X            *p++ = *s;
  643. X            continue;
  644. X        }
  645. X        switch (*++s) {
  646. X        case '/':
  647. X            *p++ = '/';
  648. X            break;
  649. X
  650. X        case '<':
  651. X            strcpy(p, BEGWORD);
  652. X            p += strlen(BEGWORD);
  653. X            begword = TRUE;
  654. X            break;
  655. X
  656. X        case '>':
  657. X            strcpy(p, ENDWORD);
  658. X            p += strlen(ENDWORD);
  659. X            break;
  660. X
  661. X        default:
  662. X            *p++ = '\\';
  663. X            *p++ = *s;
  664. X            break;
  665. X        }
  666. X    }
  667. X    *p++ = NUL;
  668. X
  669. X    return ns;
  670. X}
  671. X
  672. static char *laststr = NULL;
  673. static int lastsdir;
  674. X
  675. static LPTR *
  676. ssearch(dir,str)
  677. int    dir;    /* FORWARD or BACKWARD */
  678. char    *str;
  679. X{
  680. X    static LPTR *bcksearch(), *fwdsearch();
  681. X    LPTR    *pos;
  682. X
  683. X    if ( laststr != NULL )
  684. X        free(laststr);
  685. X    laststr = strsave(str);
  686. X    lastsdir = dir;
  687. X    if ( dir == BACKWARD )
  688. X        pos = bcksearch(mapstring(str));
  689. X    else
  690. X        pos = fwdsearch(mapstring(str));
  691. X
  692. X    /*
  693. X     * This is kind of a kludge, but its needed to make
  694. X     * 'beginning of word' searches land on the right place.
  695. X     */
  696. X    if (begword) {
  697. X        if (pos->index != 0)
  698. X            pos->index += 1;
  699. X    }
  700. X    return pos;
  701. X}
  702. X
  703. void
  704. dosearch(dir,str)
  705. int dir;
  706. char *str;
  707. X{
  708. X    LPTR *p;
  709. X
  710. X    if ((p = ssearch(dir,str)) == NULL)
  711. X        msg("Pattern not found");
  712. X    else {
  713. X        LPTR savep;
  714. X
  715. X        cursupdate();
  716. X        /* if we're backing up, we make sure the line we're on */
  717. X        /* is on the screen. */
  718. X        setpcmark();
  719. X        *Curschar = savep = *p;
  720. X        cursupdate();
  721. X    }
  722. X}
  723. X
  724. X#define    OTHERDIR(x)    (((x) == FORWARD) ? BACKWARD : FORWARD)
  725. X
  726. void
  727. repsearch(flag)
  728. int    flag;
  729. X{
  730. X    int    dir = lastsdir;
  731. X
  732. X    if ( laststr == NULL )
  733. X        beep();
  734. X    else
  735. X        dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);
  736. X
  737. X    lastsdir = dir;
  738. X}
  739. X
  740. X/*
  741. X * regerror - called by regexp routines when errors are detected.
  742. X */
  743. void
  744. regerror(s)
  745. char    *s;
  746. X{
  747. X    emsg(s);
  748. X}
  749. X
  750. static LPTR *
  751. fwdsearch(str)
  752. register char *str;
  753. X{
  754. X    static LPTR infile;
  755. X    register LPTR *p;
  756. X    regexp *prog;
  757. X    bool_t    want_start = (*str == '^');    /* looking for start of line? */
  758. X
  759. X    register char *s;
  760. X    register int i;
  761. X
  762. X    if ((prog = regcomp(str)) == NULL) {
  763. X        emsg("Invalid search string");
  764. X        return NULL;
  765. X    }
  766. X
  767. X    p = Curschar;
  768. X    i = Curschar->index + 1;
  769. X    do {
  770. X        s = p->linep->s + i;
  771. X        i = 0;
  772. X
  773. X        if (regexec(prog, s)) {        /* got a match */
  774. X            /*
  775. X             * If we wanted the start of a line and we aren't
  776. X             * really there, then a match doesn't count.
  777. X             */
  778. X            if (want_start && (s != p->linep->s))
  779. X                continue;
  780. X
  781. X            infile.linep = p->linep;
  782. X            infile.index = (int) (prog->startp[0] - p->linep->s);
  783. X            free(prog);
  784. X            return (&infile);
  785. X        }
  786. X    } while ((p = nextline(p)) != NULL);
  787. X
  788. X    /*
  789. X     * If wrapscan isn't set, then don't scan from the beginning
  790. X     * of the file. Just return failure here.
  791. X     */
  792. X    if (!P(P_WS)) {
  793. X        free(prog);
  794. X        return NULL;
  795. X    }
  796. X
  797. X    /* search from the beginning of the file to Curschar */
  798. X    for (p = Filemem; p != NULL ;p = nextline(p)) {
  799. X        s = p->linep->s;
  800. X
  801. X        if (regexec(prog, s)) {        /* got a match */
  802. X            infile.linep = p->linep;
  803. X            infile.index = (int) (prog->startp[0] - s);
  804. X            free(prog);
  805. X            return (&infile);
  806. X        }
  807. X
  808. X        if (p->linep == Curschar->linep)
  809. X            break;
  810. X    }
  811. X
  812. X    free(prog);
  813. X    return(NULL);
  814. X}
  815. X
  816. static LPTR *
  817. bcksearch(str)
  818. char *str;
  819. X{
  820. X    static LPTR infile;
  821. X    register LPTR *p;
  822. X    regexp    *prog;
  823. X    register char *s;
  824. X    register int i;
  825. X    bool_t    want_start = (*str == '^');    /* looking for start of line? */
  826. X    register char    *match;
  827. X
  828. X    /* make sure str isn't empty */
  829. X    if (str == NULL || *str == NUL)
  830. X        return NULL;
  831. X
  832. X    if ((prog = regcomp(str)) == NULL) {
  833. X        emsg("Invalid search string");
  834. X        return NULL;
  835. X    }
  836. X
  837. X    p = Curschar;
  838. X    dec(p);
  839. X
  840. X    if (begword)        /* so we don't get stuck on one match */
  841. X        dec(p);
  842. X
  843. X    i = (want_start) ? 0 : p->index;
  844. X
  845. X    do {
  846. X        s = p->linep->s;
  847. X
  848. X        if (regexec(prog, s)) {        /* match somewhere on line */
  849. X
  850. X            if (want_start) {    /* could only have been one */
  851. X                infile.linep = p->linep;
  852. X                infile.index = (int) (prog->startp[0] - s);
  853. X                free(prog);
  854. X                return (&infile);
  855. X            }
  856. X
  857. X            /*
  858. X             * Now, if there are multiple matches on this line,
  859. X             * we have to get the last one. Or the last one
  860. X             * before the cursor, if we're on that line.
  861. X             */
  862. X
  863. X            match = prog->startp[0];
  864. X
  865. X            while (regexec(prog, prog->endp[0])) {
  866. X                if ((i >= 0) && ((prog->startp[0] - s) > i))
  867. X                    break;
  868. X                match = prog->startp[0];
  869. X            }
  870. X
  871. X            if ((i >= 0) && ((match - s) > i)) {
  872. X                i = -1;
  873. X                continue;
  874. X            }
  875. X
  876. X            infile.linep = p->linep;
  877. X            infile.index = (int) (match - s);
  878. X            free(prog);
  879. X            return (&infile);
  880. X        }
  881. X        i = -1;
  882. X
  883. X    } while ((p = prevline(p)) != NULL);
  884. X
  885. X    /*
  886. X     * If wrapscan isn't set, bag the search now
  887. X     */
  888. X    if (!P(P_WS)) {
  889. X        free(prog);
  890. X        return NULL;
  891. X    }
  892. X
  893. X    /* search backward from the end of the file */
  894. X    p = prevline(Fileend);
  895. X    do {
  896. X        s = p->linep->s;
  897. X
  898. X        if (regexec(prog, s)) {        /* match somewhere on line */
  899. X
  900. X            if (want_start) {    /* could only have been one */
  901. X                infile.linep = p->linep;
  902. X                infile.index = (int) (prog->startp[0] - s);
  903. X                free(prog);
  904. X                return (&infile);
  905. X            }
  906. X
  907. X            /*
  908. X             * Now, if there are multiple matches on this line,
  909. X             * we have to get the last one.
  910. X             */
  911. X
  912. X            match = prog->startp[0];
  913. X
  914. X            while (regexec(prog, prog->endp[0]))
  915. X                match = prog->startp[0];
  916. X
  917. X            infile.linep = p->linep;
  918. X            infile.index = (int) (match - s);
  919. X            free(prog);
  920. X            return (&infile);
  921. X        }
  922. X
  923. X        if (p->linep == Curschar->linep)
  924. X            break;
  925. X
  926. X    } while ((p = prevline(p)) != NULL);
  927. X
  928. X    free(prog);
  929. X    return NULL;
  930. X}
  931. X
  932. X/*
  933. X * Character Searches
  934. X */
  935. X
  936. static char lastc = NUL;    /* last character searched for */
  937. static int  lastcdir;        /* last direction of character search */
  938. static int  lastctype;        /* last type of search ("find" or "to") */
  939. X
  940. X/*
  941. X * searchc(c, dir, type)
  942. X *
  943. X * Search for character 'c', in direction 'dir'. If type is 0, move to
  944. X * the position of the character, otherwise move to just before the char.
  945. X */
  946. bool_t
  947. searchc(c, dir, type)
  948. char    c;
  949. int    dir;
  950. int    type;
  951. X{
  952. X    LPTR    save;
  953. X
  954. X    save = *Curschar;    /* save position in case we fail */
  955. X    lastc = c;
  956. X    lastcdir = dir;
  957. X    lastctype = type;
  958. X
  959. X    /*
  960. X     * On 'to' searches, skip one to start with so we can repeat
  961. X     * searches in the same direction and have it work right.
  962. X     */
  963. X    if (type)
  964. X        (dir == FORWARD) ? oneright() : oneleft();
  965. X
  966. X    while ( (dir == FORWARD) ? oneright() : oneleft() ) {
  967. X        if (gchar(Curschar) == c) {
  968. X            if (type)
  969. X                (dir == FORWARD) ? oneleft() : oneright();
  970. X            return TRUE;
  971. X        }
  972. X    }
  973. X    *Curschar = save;
  974. X    return FALSE;
  975. X}
  976. X
  977. bool_t
  978. crepsearch(flag)
  979. int    flag;
  980. X{
  981. X    int    dir = lastcdir;
  982. X    int    rval;
  983. X
  984. X    if (lastc == NUL)
  985. X        return FALSE;
  986. X
  987. X    rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);
  988. X
  989. X    lastcdir = dir;        /* restore dir., since it may have changed */
  990. X
  991. X    return rval;
  992. X}
  993. X
  994. X/*
  995. X * "Other" Searches
  996. X */
  997. X
  998. X/*
  999. X * showmatch - move the cursor to the matching paren or brace
  1000. X */
  1001. LPTR *
  1002. showmatch()
  1003. X{
  1004. X    static    LPTR    pos;
  1005. X    int    (*move)(), inc(), dec();
  1006. X    char    initc = gchar(Curschar);    /* initial char */
  1007. X    char    findc;                /* terminating char */
  1008. X    char    c;
  1009. X    int    count = 0;
  1010. X
  1011. X    pos = *Curschar;        /* set starting point */
  1012. X
  1013. X    switch (initc) {
  1014. X
  1015. X    case '(':
  1016. X        findc = ')';
  1017. X        move = inc;
  1018. X        break;
  1019. X    case ')':
  1020. X        findc = '(';
  1021. X        move = dec;
  1022. X        break;
  1023. X    case '{':
  1024. X        findc = '}';
  1025. X        move = inc;
  1026. X        break;
  1027. X    case '}':
  1028. X        findc = '{';
  1029. X        move = dec;
  1030. X        break;
  1031. X    case '[':
  1032. X        findc = ']';
  1033. X        move = inc;
  1034. X        break;
  1035. X    case ']':
  1036. X        findc = '[';
  1037. X        move = dec;
  1038. X        break;
  1039. X    default:
  1040. X        return (LPTR *) NULL;
  1041. X    }
  1042. X
  1043. X    while ((*move)(&pos) != -1) {        /* until end of file */
  1044. X        c = gchar(&pos);
  1045. X        if (c == initc)
  1046. X            count++;
  1047. X        else if (c == findc) {
  1048. X            if (count == 0)
  1049. X                return &pos;
  1050. X            count--;
  1051. X        }
  1052. X    }
  1053. X    return (LPTR *) NULL;            /* never found it */
  1054. X}
  1055. X
  1056. X/*
  1057. X * findfunc(dir) - Find the next function in direction 'dir'
  1058. X *
  1059. X * Return TRUE if a function was found.
  1060. X */
  1061. bool_t
  1062. findfunc(dir)
  1063. int    dir;
  1064. X{
  1065. X    LPTR    *curr;
  1066. X
  1067. X    curr = Curschar;
  1068. X
  1069. X    do {
  1070. X        curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);
  1071. X
  1072. X        if (curr != NULL && curr->linep->s[0] == '{') {
  1073. X            setpcmark();
  1074. X            *Curschar = *curr;
  1075. X            return TRUE;
  1076. X        }
  1077. X    } while (curr != NULL);
  1078. X
  1079. X    return FALSE;
  1080. X}
  1081. X
  1082. X/*
  1083. X * The following routines do the word searches performed by the
  1084. X * 'w', 'W', 'b', 'B', 'e', and 'E' commands.
  1085. X */
  1086. X
  1087. X/*
  1088. X * To perform these searches, characters are placed into one of three
  1089. X * classes, and transitions between classes determine word boundaries.
  1090. X *
  1091. X * The classes are:
  1092. X *
  1093. X * 0 - white space
  1094. X * 1 - letters, digits, and underscore
  1095. X * 2 - everything else
  1096. X */
  1097. X
  1098. static    int    stype;        /* type of the word motion being performed */
  1099. X
  1100. X#define    C0(c)    (((c) == ' ') || ((c) == '\t') || ((c) == NUL))
  1101. X#define    C1(c)    (isalpha(c) || isdigit(c) || ((c) == '_'))
  1102. X
  1103. X/*
  1104. X * cls(c) - returns the class of character 'c'
  1105. X *
  1106. X * The 'type' of the current search modifies the classes of characters
  1107. X * if a 'W', 'B', or 'E' motion is being done. In this case, chars. from
  1108. X * class 2 are reported as class 1 since only white space boundaries are
  1109. X * of interest.
  1110. X */
  1111. static    int
  1112. cls(c)
  1113. char    c;
  1114. X{
  1115. X    if (C0(c))
  1116. X        return 0;
  1117. X
  1118. X    if (C1(c))
  1119. X        return 1;
  1120. X
  1121. X    /*
  1122. X     * If stype is non-zero, report these as class 1.
  1123. X     */
  1124. X    return (stype == 0) ? 2 : 1;
  1125. X}
  1126. X
  1127. X
  1128. X/*
  1129. X * fwd_word(pos, type) - move forward one word
  1130. X *
  1131. X * Returns the resulting position, or NULL if EOF was reached.
  1132. X */
  1133. LPTR *
  1134. fwd_word(p, type)
  1135. LPTR    *p;
  1136. int    type;
  1137. X{
  1138. X    static    LPTR    pos;
  1139. X    int    sclass = cls(gchar(p));        /* starting class */
  1140. X
  1141. X    pos = *p;
  1142. X
  1143. X    stype = type;
  1144. X
  1145. X    /*
  1146. X     * We always move at least one character.
  1147. X     */
  1148. X    if (inc(&pos) == -1)
  1149. X        return NULL;
  1150. X
  1151. X    if (sclass != 0) {
  1152. X        while (cls(gchar(&pos)) == sclass) {
  1153. X            if (inc(&pos) == -1)
  1154. X                return NULL;
  1155. X        }
  1156. X        /*
  1157. X         * If we went from 1 -> 2 or 2 -> 1, return here.
  1158. X         */
  1159. X        if (cls(gchar(&pos)) != 0)
  1160. X            return &pos;
  1161. X    }
  1162. X
  1163. X    /* We're in white space; go to next non-white */
  1164. X
  1165. X    while (cls(gchar(&pos)) == 0) {
  1166. X        /*
  1167. X         * We'll stop if we land on a blank line
  1168. X         */
  1169. X        if (pos.index == 0 && pos.linep->s[0] == NUL)
  1170. X            break;
  1171. X
  1172. X        if (inc(&pos) == -1)
  1173. X            return NULL;
  1174. X    }
  1175. X
  1176. X    return &pos;
  1177. X}
  1178. X
  1179. X/*
  1180. X * bck_word(pos, type) - move backward one word
  1181. X *
  1182. X * Returns the resulting position, or NULL if EOF was reached.
  1183. X */
  1184. LPTR *
  1185. bck_word(p, type)
  1186. LPTR    *p;
  1187. int    type;
  1188. X{
  1189. X    static    LPTR    pos;
  1190. X    int    sclass = cls(gchar(p));        /* starting class */
  1191. X
  1192. X    pos = *p;
  1193. X
  1194. X    stype = type;
  1195. X
  1196. X    if (dec(&pos) == -1)
  1197. X        return NULL;
  1198. X
  1199. X    /*
  1200. X     * If we're in the middle of a word, we just have to
  1201. X     * back up to the start of it.
  1202. X     */
  1203. X    if (cls(gchar(&pos)) == sclass && sclass != 0) {
  1204. X        /*
  1205. X         * Move backward to start of the current word
  1206. X         */
  1207. X        while (cls(gchar(&pos)) == sclass) {
  1208. X            if (dec(&pos) == -1)
  1209. X                return NULL;
  1210. X        }
  1211. X        inc(&pos);            /* overshot - forward one */
  1212. X        return &pos;
  1213. X    }
  1214. X
  1215. X    /*
  1216. X     * We were at the start of a word. Go back to the start
  1217. X     * of the prior word.
  1218. X     */
  1219. X
  1220. X    while (cls(gchar(&pos)) == 0) {        /* skip any white space */
  1221. X        /*
  1222. X         * We'll stop if we land on a blank line
  1223. X         */
  1224. X        if (pos.index == 0 && pos.linep->s[0] == NUL)
  1225. X            return &pos;
  1226. X
  1227. X        if (dec(&pos) == -1)
  1228. X            return NULL;
  1229. X    }
  1230. X
  1231. X    sclass = cls(gchar(&pos));
  1232. X
  1233. X    /*
  1234. X     * Move backward to start of this word.
  1235. X     */
  1236. X    while (cls(gchar(&pos)) == sclass) {
  1237. X        if (dec(&pos) == -1)
  1238. X            return NULL;
  1239. X    }
  1240. X    inc(&pos);            /* overshot - forward one */
  1241. X
  1242. X    return &pos;
  1243. X}
  1244. X
  1245. X/*
  1246. X * end_word(pos, type) - move to the end of the word
  1247. X *
  1248. X * There is an apparent bug in the 'e' motion of the real vi. At least
  1249. X * on the System V Release 3 version for the 80386. Unlike 'b' and 'w',
  1250. X * the 'e' motion crosses blank lines. When the real vi crosses a blank
  1251. X * line in an 'e' motion, the cursor is placed on the FIRST character
  1252. X * of the next non-blank line. The 'E' command, however, works correctly.
  1253. X * Since this appears to be a bug, I have not duplicated it here.
  1254. X *
  1255. X * Returns the resulting position, or NULL if EOF was reached.
  1256. X */
  1257. LPTR *
  1258. end_word(p, type)
  1259. LPTR    *p;
  1260. int    type;
  1261. X{
  1262. X    static    LPTR    pos;
  1263. X    int    sclass = cls(gchar(p));        /* starting class */
  1264. X
  1265. X    pos = *p;
  1266. X
  1267. X    stype = type;
  1268. X
  1269. X    if (inc(&pos) == -1)
  1270. X        return NULL;
  1271. X
  1272. X    /*
  1273. X     * If we're in the middle of a word, we just have to
  1274. X     * move to the end of it.
  1275. X     */
  1276. X    if (cls(gchar(&pos)) == sclass && sclass != 0) {
  1277. X        /*
  1278. X         * Move forward to end of the current word
  1279. X         */
  1280. X        while (cls(gchar(&pos)) == sclass) {
  1281. X            if (inc(&pos) == -1)
  1282. X                return NULL;
  1283. X        }
  1284. X        dec(&pos);            /* overshot - forward one */
  1285. X        return &pos;
  1286. X    }
  1287. X
  1288. X    /*
  1289. X     * We were at the end of a word. Go to the end
  1290. X     * of the next word.
  1291. X     */
  1292. X
  1293. X    while (cls(gchar(&pos)) == 0) {        /* skip any white space */
  1294. X        if (inc(&pos) == -1)
  1295. X            return NULL;
  1296. X    }
  1297. X
  1298. X    sclass = cls(gchar(&pos));
  1299. X
  1300. X    /*
  1301. X     * Move forward to end of this word.
  1302. X     */
  1303. X    while (cls(gchar(&pos)) == sclass) {
  1304. X        if (inc(&pos) == -1)
  1305. X            return NULL;
  1306. X    }
  1307. X    dec(&pos);            /* overshot - forward one */
  1308. X
  1309. X    return &pos;
  1310. X}
  1311. END_OF_FILE
  1312. if test 13221 -ne `wc -c <'search.c'`; then
  1313.     echo shar: \"'search.c'\" unpacked with wrong size!
  1314. fi
  1315. # end of 'search.c'
  1316. fi
  1317. if test -f 'stevie.doc' -a "${1}" != "-c" ; then 
  1318.   echo shar: Will not clobber existing file \"'stevie.doc'\"
  1319. else
  1320. echo shar: Extracting \"'stevie.doc'\" \(15622 characters\)
  1321. sed "s/^X//" >'stevie.doc' <<'END_OF_FILE'
  1322. X
  1323. X             STEVIE - An Aspiring VI Clone
  1324. X
  1325. X                 User Reference
  1326. X
  1327. X                  Tony Andrews
  1328. X
  1329. X                  3/6/88
  1330. X
  1331. X
  1332. Overview
  1333. X--------
  1334. X
  1335. STEVIE is an editor designed to mimic the interface of the UNIX editor
  1336. X'vi'. The name (ST Editor for VI Enthusiasts) is due to the fact that
  1337. the editor was first written for the Atari ST. The current version has
  1338. been ported to UNIX and OS/2, but I've left the name intact for now.
  1339. X
  1340. I've labelled STEVIE an 'aspiring' vi clone as a warning to those who
  1341. may expect too much. On the whole, the editor is pretty complete. Almost
  1342. all of the visual mode commands are supported. The biggest failing at the
  1343. moment is that the undo command is currently in a state of disrepair.
  1344. Recent enhancements in other areas have required the undo command to be
  1345. mostly disabled until it can catch up with the other changes. But don't be
  1346. discouraged. I've tried very hard to capture the 'feel' of vi by getting
  1347. the little things right. Making lines wrap correctly, supporting true
  1348. operators, and even getting the cursor to land on the right place for
  1349. tabs are all a real pain, but do much to make the editor feel right.
  1350. X
  1351. This program is the result of many late nights of hacking over the last
  1352. several months. The first version was written by Tim Thompson and posted
  1353. to USENET. From there, I reworked the data structures completely, added
  1354. LOTS of features, and generally improved the overall performance in the
  1355. process.
  1356. X
  1357. STEVIE may be freely distributed. The source isn't copyrighted or
  1358. restricted in any way. If you pass the program along, please include all
  1359. the documentation and, if practical, the source as well. I'm not fanatical
  1360. about this, but I tried to make STEVIE fairly portable and that doesn't
  1361. do any good if the source isn't available.
  1362. X
  1363. The remainder of this document describes the operation of the editor.
  1364. This is intended as a reference for users already familiar with the real
  1365. vi editor.
  1366. X
  1367. X
  1368. Starting the Editor
  1369. X-------------------
  1370. X
  1371. The following command line forms are supported:
  1372. X
  1373. X    vi [file ...]        Edit the specified file(s)
  1374. X
  1375. X    vi -t tag        Start at location of the given tag
  1376. X
  1377. X    vi + file        Edit file starting at end
  1378. X
  1379. X    vi +n file        Edit file starting a line number 'n'
  1380. X
  1381. X    vi +/pat file        Edit file starting at pattern 'pat'
  1382. X
  1383. If multiple files are given on the command line (using the first form),
  1384. the ":n" command goes to the next file, ":p" goes backward in the list,
  1385. and ":rew" can be used to rewind back to the start of the file list.
  1386. X
  1387. X
  1388. Set Command Options
  1389. X-------------------
  1390. X
  1391. The ":set" command works as usual to set parameters. Each parameter has
  1392. a long and an abbreviated name, either of which may be used. Boolean
  1393. parameters are set as in:
  1394. X
  1395. X    set showmatch
  1396. X
  1397. or cleared by:
  1398. X
  1399. X    set noshowmatch
  1400. X
  1401. Numeric parameters are set as in:
  1402. X
  1403. X    set scroll=5
  1404. X
  1405. Several parameters may be set with a single command:
  1406. X
  1407. X    set novb sm report=1
  1408. X
  1409. To see the status of all parameters use ":set all". Typing ":set" with
  1410. no arguments will show only those parameters that have been changed.
  1411. The supported parameters, their names, defaults, and descriptions are
  1412. shown below:
  1413. X
  1414. XFull Name    Short    Default        Description
  1415. X------------------------------------------------------------------------------
  1416. vbell        vb    vb        Use visual bell (novb for audible bell)
  1417. showmatch    sm    nosm        Showmatch mode
  1418. wrapscan    ws    ws        Wrapscan (searches cross file start/end)
  1419. errorbells    eb    noeb        Ring bell when error messages are shown
  1420. showmode    mo    nomo        Show on status line when in insert mode
  1421. backup        bk    nobk        Leave backup in *.bak on file writes
  1422. return        cr    cr        End lines with cr-lf when writing
  1423. list        list    nolist        Show tabs and newlines graphically
  1424. X
  1425. scroll        scroll    12        Number of lines to scroll for ^D and ^U
  1426. tabstop        ts    8        Number of spaces in a tab
  1427. report        report    5        Min # of lines to report operations on
  1428. lines        lines    25        Number of lines on the screen
  1429. X
  1430. X
  1431. The EXINIT environment variable can be used to modify the default values
  1432. on startup as in:
  1433. X
  1434. X        setenv EXINIT="set sm ts=4"
  1435. X
  1436. The 'backup' parameter, if set, causes the editor to retain a backup of any
  1437. files that are written. During file writes, a backup is always kept for
  1438. safety until the write is completed. At that point, the 'backup' parameter
  1439. determines whether the backup file is deleted.
  1440. X
  1441. In environments (e.g. OS/2 or TOS) where lines are normally terminated by
  1442. CR-LF, the 'return' parameter allows files to be written with only a LF
  1443. terminator (if the parameter is cleared).
  1444. X
  1445. The 'lines' parameter tells the editor how many lines there are on the screen.
  1446. This is useful on systems like the ST where various screen resolutions may be
  1447. used. By using the 'lines' parameter, different screen sizes can be easily
  1448. handled.
  1449. X
  1450. X
  1451. XFile Manipulation Commands
  1452. X--------------------------
  1453. X
  1454. The following table shows the supported file manipulation commands as
  1455. well as some other 'ex' commands that aren't described elsewhere:
  1456. X
  1457. X:w        write the current file
  1458. X:wq        write and quit
  1459. X:x        write (if necessary) and quit
  1460. ZZ        same as ":x"
  1461. X
  1462. X:e file        edit the named file
  1463. X:e!        re-edit the current file, discarding any changes
  1464. X:e #        edit the alternate file
  1465. X
  1466. X:w file        write the buffer to the named file
  1467. X:x,y w file    write lines x through y to the named file
  1468. X:r file        read the named file into the buffer
  1469. X
  1470. X:n        edit the next file
  1471. X:p        edit the previous file
  1472. X:rew        rewind the file list
  1473. X
  1474. X:f        show the current file name
  1475. X:f name        change the current file name
  1476. X
  1477. X:ta tag        go to the named tag
  1478. X^]        like ":ta" using the current word as the tag
  1479. X
  1480. X:help        display a command summary
  1481. X
  1482. The ":help" command can also be invoke with the <HELP> key on the Atari
  1483. ST. This actually displays a pretty complete summary of the real vi with
  1484. unsupported features indicated appropriately.
  1485. X
  1486. The commands above work pretty much like they do in 'vi'. Most of the
  1487. commands support a '!' suffix (if appropriate) to discard any pending
  1488. changes.
  1489. X
  1490. When writing just part of the buffer, the following address forms are
  1491. supported:
  1492. X
  1493. X        addr [+- number]
  1494. X
  1495. where 'addr' may be one of the following:
  1496. X
  1497. X        a line number
  1498. X        a mark (as in 'a or 'b)
  1499. X        '.' (the current line)
  1500. X        '$' (the last line)
  1501. X
  1502. X
  1503. String Searches
  1504. X---------------
  1505. X
  1506. String searches are supported, as in vi, accepting the usual regular
  1507. expression syntax. This was done using Henry Spencer's regular expression
  1508. library without modification. I added code outside the library to support
  1509. the '\<' and '\>' extensions. This actually turned out to be pretty easy.
  1510. X
  1511. X
  1512. Operators
  1513. X---------
  1514. X
  1515. The vi operators (d, c, y, <, and >) work as true operators. The only
  1516. exception is that the change operator works only for character-oriented
  1517. changes (like cw or c%) and not for line-oriented changes (like cL or c3j).
  1518. X
  1519. X
  1520. Tags
  1521. X----
  1522. X
  1523. Tags are implemented and a fairly simple version of 'ctags' is supplied
  1524. with the editor. The current version of ctags will find functions and
  1525. macros following a specific (but common) form.  See 'ctags.doc' for a
  1526. complete discussion.  [The full Ctags program is in the public domain;
  1527. contact your nearest comp.sources.unix archive site; the primitive
  1528. tags has been taken out of this c.s.u distribution.]
  1529. X
  1530. X
  1531. System-Specific Comments
  1532. X------------------------
  1533. X
  1534. The following sections provide additional relevant information for the
  1535. systems to which STEVIE has been ported.
  1536. X
  1537. X
  1538. Atari ST
  1539. X--------
  1540. X
  1541. The editor has been tested in all three resolutions, although low and
  1542. high res. are less tested than medium. The 50-line high res. mode can
  1543. be used by setting the 'lines' parameter to 50. Alternatively, the
  1544. environment variable 'LINES' can be set. The editor doesn't actively
  1545. set the number of lines on the screen. It just operates using the number
  1546. of lines it was told.
  1547. X
  1548. The arrow keys, as well as the <INSERT>, <HELP>, and <UNDO> keys are
  1549. all mapped appropriately.
  1550. X
  1551. X
  1552. UNIX
  1553. X----
  1554. X
  1555. The editor has been ported to UNIX System V release 3. This was done
  1556. mainly to get some profiling data so I haven't put much effort into
  1557. doing the UNIX version right. It's hard-coded for ansi-style escape
  1558. sequences and doesn't use the termcap/terminfo routines at all.
  1559. X
  1560. X
  1561. OS/2
  1562. X----
  1563. X
  1564. This port was done because the editor that comes with the OS/2 developer's
  1565. kit really sucks. Make sure 'ansi' mode is on (using the 'ansi' command).
  1566. The OS/2 ansi driver doesn't support insert/delete line, so the display
  1567. updates are a little rough, but the editor is fast enough that it isn't
  1568. too bothersome. The arrow keys are NOT mapped, so they don't currently do
  1569. anything reasonable.
  1570. X
  1571. X
  1572. Missing Features
  1573. X----------------
  1574. X
  1575. X1. Counts aren't yet supported everywhere that they should be.
  1576. X
  1577. X2. Macros with support for the ST function keys.
  1578. X
  1579. X3. More "set" options.
  1580. X
  1581. X4. Auto-indent.
  1582. X
  1583. X5. Many others...
  1584. X
  1585. X
  1586. X
  1587. Known Bugs and Problems
  1588. X-----------------------
  1589. X
  1590. X1. Undo is partially disabled until I can re-work some of the code for
  1591. X   undoing certain edit operations. Undo is enabled for those operations
  1592. X   where I've specifically checked out the code. All other cases print
  1593. X   an apologetic message for the time being. Recent changes to the editor
  1594. X   broke some of the old 'undo' code. This is a temporary hack until I
  1595. X   can check out all the undo code.
  1596. X
  1597. X2. The change operator is only half-way implemented. It works for character
  1598. X   motions but not line motions. This isn't so bad since most change
  1599. X   operations are character oriented anyway.
  1600. X
  1601. X3. The yank buffer uses statically allocated memory, so yanks of more than
  1602. X   1K of text will fail. If a delete spans more than 1K, the program asks
  1603. X   for confirmation before proceeding. That way, if you were moving text,
  1604. X   you don't get screwed by the limited yank buffer. You just have to move
  1605. X   smaller chunks at a time. All the internal buffers (yank, redo, etc.)
  1606. X   need to be reworked to allocate memory dynamically.
  1607. X
  1608. X4. If you stay in insert mode for a long time, the insert buffer can overflow.
  1609. X   The editor will print a message and dump you back into command mode.
  1610. X
  1611. X5. Puts are very slow.
  1612. X
  1613. X6. Several other less bothersome glitches...
  1614. X
  1615. X
  1616. Conclusion
  1617. X----------
  1618. X
  1619. I'm still working on the program pretty actively, although the farther I
  1620. get with it, the harder it is to get motivated to work on it. I've been
  1621. using it as my standard editor for a long time, and I suppose I'm coming
  1622. to accept its deficiencies more than I should. Fortunately, I use the
  1623. real vi every day at work, so I'm constantly reminded of the work that
  1624. remains to be done.
  1625. X
  1626. I'd like to thank Tim Thompson for writing the original version of the
  1627. editor. His program was well structured and quite readable. Thanks for
  1628. giving me a good base to work with.
  1629. X
  1630. If you're reading this file, but didn't get the source code for STEVIE,
  1631. it can be had by sending a disk with return postage to the address given
  1632. below. I can write disks for the Atari ST (SS or DS) or MSDOS (360K or
  1633. X1.2M). Please be sure to include the return postage. I don't intend to
  1634. make money from this program, but I don't want to lose any either.
  1635. X
  1636. I'm not planning to try to coordinate the various ports of STEVIE that
  1637. may occur. I just don't have the time. But if you do port it, I'd be
  1638. interested in hearing about it. I will be doing a port for Minix on the
  1639. ST when that becomes available later this year. So if anyone does a
  1640. Minix port on the PC, I'd be especially interested.
  1641. X
  1642. X
  1643. Tony Andrews            UUCP: onecom!wldrdg!tony
  1644. X5902E Gunbarrel Ave.
  1645. Boulder, CO 80301
  1646. X
  1647. X
  1648. Character Function Summary
  1649. X--------------------------
  1650. X
  1651. The following list describes the meaning of each character that's used
  1652. by the editor. In some cases characters have meaning in both command and
  1653. insert mode; these are all described.
  1654. X
  1655. X^@    The null character. Not used in any mode. This character may not
  1656. X    be present in the file, as is the case with vi.
  1657. X
  1658. X^B    Backward one screen.
  1659. X
  1660. X^D    Scroll the window down one half screen.
  1661. X
  1662. X^E    Scroll the screen up one line.
  1663. X
  1664. X^F    Forward one screen.
  1665. X
  1666. X^G    Same as ":f" command. Displays file information.
  1667. X
  1668. X^H (BS)    Moves cursor left one space in command mode. In insert mode, erases
  1669. X    the last character typed.
  1670. X
  1671. X^J    Move the cursor down one line.
  1672. X
  1673. X^L    Clear and redraw the screen.
  1674. X
  1675. X^M (CR)    Move to the first non-white character in the next line. In insert
  1676. X    mode, a carriage return opens a new line for input.
  1677. X
  1678. X^N    Move the cursor down a line.
  1679. X
  1680. X^P    Move the cursor up a line.
  1681. X
  1682. X^U    Scroll the window up one half screen.
  1683. X
  1684. X^Y    Scroll the screen down one line.
  1685. X
  1686. X^[    Escape cancels a pending command in command mode, and is used to
  1687. X    terminate insert mode.
  1688. X
  1689. X^]    Moves to the tag whose name is given by the word in which the cursor
  1690. X    resides.
  1691. X
  1692. X^`    Same as ":e #" if supported (system-dependent).
  1693. X
  1694. SPACE    Move the cursor right on column.
  1695. X
  1696. X$    Move to the end of the current line.
  1697. X
  1698. X%    If the cursor rests on a paren '()', brace '{}', or bracket '[]',
  1699. X    move to the matching one.
  1700. X
  1701. X'    Used to move the cursor to a previously marked position, as in
  1702. X    'a or 'b. The cursor moves to the start of the marked line. The
  1703. X    special mark '' refers to the "previous context".
  1704. X
  1705. X+    Same as carriage return, in command mode.
  1706. X
  1707. X,    Reverse of the last t, T, f, or F command.
  1708. X
  1709. X-    Move to the first non-white character in the previous line.
  1710. X
  1711. X.    Repeat the last edit command.
  1712. X
  1713. X/    Start of a forward string search command. String searches may be
  1714. X    optionally terminated with a closing slash. To search for a slash
  1715. X    use '\/' in the search string.
  1716. X
  1717. X0    Move to the start of the current line. Also used within counts.
  1718. X
  1719. X1-9    Used to add 'count' prefixes to commands.
  1720. X
  1721. X:    Prefix character for "ex" commands.
  1722. X
  1723. X;    Repeat last t, T, f, or F command.
  1724. X
  1725. X<    The 'left shift' operator.
  1726. X
  1727. X>    The 'right shift' operator.
  1728. X
  1729. X?    Same as '/', but search backward.
  1730. X
  1731. A    Append at the end of the current line.
  1732. X
  1733. B    Backward one blank-delimited word.
  1734. X
  1735. C    Change the rest of the current line.
  1736. X
  1737. D    Delete the rest of the current line.
  1738. X
  1739. XE    End of the end of a blank-delimited word.
  1740. X
  1741. XF    Find a character backward on the current line.
  1742. X
  1743. G    Go to the given line number (end of file, by default).
  1744. X
  1745. H    Move to the first non-white char. on the top screen line.
  1746. X
  1747. I    Insert before the first non-white char. on the current line.
  1748. X
  1749. J    Join two lines.
  1750. X
  1751. L    Move to the first non-white char. on the bottom screen line.
  1752. X
  1753. M    Move to the first non-white char. on the middle screen line.
  1754. X
  1755. N    Reverse the last string search.
  1756. X
  1757. O    Open a new line above the current line, and start inserting.
  1758. X
  1759. P    Put the yank/delete buffer before the current cursor position.
  1760. X
  1761. T    Reverse search 'upto' the given character.
  1762. X
  1763. W    Move forward one blank-delimited word.
  1764. X
  1765. XX    Delete one character before the cursor.
  1766. X
  1767. Y    Yank the current line. Same as 'yy'.
  1768. X
  1769. ZZ    Exit from the editor, saving changes if necessary.
  1770. X
  1771. X[[    Move backward one C function.
  1772. X
  1773. X]]    Move forward one C function.
  1774. X
  1775. X^    Move to the first non-white on the current line.
  1776. X
  1777. X`    Move to the given mark, as with '. The distinction between the two
  1778. X    commands is important when used with operators. I support the
  1779. X    difference correctly. If you don't know what I'm talking about,
  1780. X    don't worry, it won't matter to you.
  1781. X
  1782. a    Append text after the cursor.
  1783. X
  1784. b    Back one word.
  1785. X
  1786. c    The change operator.
  1787. X
  1788. d    The delete operator.
  1789. X
  1790. e    Move to the end of a word.
  1791. X
  1792. f    Find a character on the current line.
  1793. X
  1794. h    Move left one column.
  1795. X
  1796. i    Insert text before the cursor.
  1797. X
  1798. j    Move down one line.
  1799. X
  1800. k    Move up one line.
  1801. X
  1802. l    Move right one column.
  1803. X
  1804. m    Set a mark at the current position (e.g. ma or mb).
  1805. X
  1806. n    Repeat the last string search.
  1807. X
  1808. o    Open a new line and start inserting text.
  1809. X
  1810. p    Put the yank/delete buffer after the cursor.
  1811. X
  1812. r    Replace a character.
  1813. X
  1814. s    Replace characters.
  1815. X
  1816. t    Move forward 'upto' the given character on the current line.
  1817. X
  1818. u    Undo the last edit. This isn't currently supported very well.
  1819. X
  1820. w    Move forward one word.
  1821. X
  1822. x    Delete the character under the cursor.
  1823. X
  1824. y    The yank operator.
  1825. X
  1826. z    Redraw the screen with the current line at the top (zRETURN),
  1827. X    the middle (z.), or the bottom (z-).
  1828. X
  1829. X|    Move to the column given by the preceding count.
  1830. X
  1831. END_OF_FILE
  1832. if test 15622 -ne `wc -c <'stevie.doc'`; then
  1833.     echo shar: \"'stevie.doc'\" unpacked with wrong size!
  1834. fi
  1835. # end of 'stevie.doc'
  1836. fi
  1837. echo shar: End of archive 3 \(of 4\).
  1838. cp /dev/null ark3isdone
  1839. MISSING=""
  1840. for I in 1 2 3 4 ; do
  1841.     if test ! -f ark${I}isdone ; then
  1842.     MISSING="${MISSING} ${I}"
  1843.     fi
  1844. done
  1845. if test "${MISSING}" = "" ; then
  1846.     echo You have unpacked all 4 archives.
  1847.     rm -f ark[1-9]isdone
  1848. else
  1849.     echo You still need to unpack the following archives:
  1850.     echo "        " ${MISSING}
  1851. fi
  1852. ##  End of shell archive.
  1853. exit 0
  1854.